package cn.hfjava.kz.controller;

import cn.dev33.satoken.stp.SaLoginConfig;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import cn.hfjava.kz.entity.dto.*;
import cn.hfjava.kz.utils.AliOssUtil;
import cn.hfjava.kz.validator.group.UpdateGroup;
import cn.hfjava.kz.entity.po.User;
import cn.hfjava.kz.entity.vo.PageVO;
import cn.hfjava.kz.entity.vo.UserVO;
import cn.hfjava.kz.service.UserService;
import cn.hutool.core.io.file.FileNameUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.MultipartConfigElement;
import jakarta.validation.groups.Default;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/auth")
@Tag(name = "用户管理模块", description = "用户管理模块接口")
public class UserController {

    private final UserService userService;
    private static final List<String> IMAGE_TYPE = Arrays.asList("png","jpg","jpeg");
    private static final List<String> FILE_TYPE = Arrays.asList("pdf","doc","docx");

    @Resource
    private BCryptPasswordEncoder passwordEncoder;
    @Autowired
    private AliOssUtil aliOssUtil;
    @Resource
    private MultipartConfigElement multipartConfigElement;

    @PostMapping("/login")
    @Operation(summary = "账号登录", description = "用户登录接口")
    public SaResult login(@RequestBody @Validated LoginUserDTO loginUserDto) {

        String encode = passwordEncoder.encode(loginUserDto.getPassword());
        System.out.println("encode:" + encode);
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.eq(User::getUsername, loginUserDto.getUsername());
        User user = userService.getOne(lqw);
        if (Objects.isNull(user)) {
            return SaResult.error("用户不存在，请重新输入");
        } else {
            if (!passwordEncoder.matches(loginUserDto.getPassword(), user.getPassword())) {
                return SaResult.error("密码错误,请重新输入");
            } else if (user.getStatus() == 1) {
                return SaResult.error("账号已被锁定,请联系管理员");
            } else {
                StpUtil.login(user.getId(), SaLoginConfig
                        .setExtra("name", user.getName()));

                String tokenName = StpUtil.getTokenName();
                String tokenValue = StpUtil.getTokenValue();
                user.setTokenName(tokenName);
                user.setTokenValue(tokenValue);
                user.setPassword("");
                // 第3步，返回给前端
                return SaResult.data(user);
            }
        }
    }


    @Operation(summary = "获取用户信息")
    @GetMapping("/info")
    public SaResult info() {
        Integer userId = Integer.valueOf(StpUtil.getLoginId().toString());   // 获取当前会话账号id, 如果未登录，则抛出异常
        User user = userService.getById(userId);
        user.setPassword("");
        return SaResult.ok().setData(user);
    }


    @Operation(summary = "退出登录")
    @GetMapping("/logout")
    public SaResult logout() {
        StpUtil.logout();
        return SaResult.ok();
    }


    @Operation(summary = "重置密码")
    @PostMapping("/resetPassword")
    public SaResult resetPassword() {
        Integer userId = Integer.valueOf(StpUtil.getLoginId().toString());
        User user = userService.getById(userId);
        String phone = user.getPhone();
        String password = phone.substring(phone.length() - 6);
        String ciphertext = passwordEncoder.encode(password);
        user.setPassword(ciphertext);
        LambdaUpdateWrapper<User> uw = new LambdaUpdateWrapper<>();
        uw.set(User::getPassword, ciphertext);
        uw.eq(User::getId, userId);
        userService.update(null, uw);
        return SaResult.ok("重置密码成功");
    }

    @Operation(summary = "新增用户")
    @PostMapping("/add")
    public SaResult addUser(@Validated(Default.class) @RequestBody UserFormDTO userDto) {
        //该用户名已存在，或被其他用户占用
        User userEntity = new User();
        //将前端传入的UserDTO对象中的数据拷贝到User持久对象
        BeanUtils.copyProperties(userDto, userEntity);
        userEntity.setPassword(passwordEncoder.encode(userEntity.getPassword()));
        userService.save(userEntity);
        return SaResult.ok("保存用户信息成功");
    }



    @Operation(summary = "修改用户")
    @PutMapping("/update")
    public SaResult updateUser(@Validated(UpdateGroup.class) @RequestBody UserFormDTO userDto) {
        //该用户名不存在，修改失败
        User userEntity = new User();
        //将前端传入的UserDTO对象中的数据拷贝到User持久对象
        BeanUtils.copyProperties(userDto, userEntity);
        userService.updateById(userEntity);
        return SaResult.ok("修改用户信息成功");
    }

    //根据（name、userName、roleId、status）组合条件分页查询用户信息(隐藏内置超级管理员)
    @PostMapping("/list")
    @Operation(summary = "按组合条件分页查询用户信息")
    public SaResult listPage(@RequestBody UserQueryDTO userQueryDto){
        PageVO<UserVO> pageVO = userService.findByPage(userQueryDto);
        return SaResult.ok("查询成功").setData(pageVO);
    }

    @DeleteMapping("/delete/{userid}")
    @Operation(summary = "删除用户", description = "根据用户ID删除指定用户")
    public SaResult deleteById(@PathVariable(value = "userid") Integer userid) {
        User user = userService.getById(userid);
        if(user == null){
            return SaResult.error("此用户不存在");
        }
        if(user.getRoleId() != null && user.getRoleId() > 0) {
            return SaResult.error("此用户已绑定角色");
        }
        userService.removeById(userid);
        return SaResult.ok("用户删除成功！");
    }
    //忘记密码
    @PostMapping("/forgetPassword")
    @Operation(summary ="忘记密码",description = "忘记密码接口，需要用户名，手机号")
    public SaResult forgetPassword(@RequestBody @Validated ForgetPasswordDto forgetPasswordDto){
        return userService.forgetPassword(forgetPasswordDto);
    }
    //验证短信
    @PostMapping("/verifyCode")
    @Operation(summary = "验证短信",description = "验证短信,需要验证码code和用户名")
    public SaResult verifyCode(@RequestBody@Validated ForgetPasswordDto forgetPasswordDto){
        return userService.verifyCode(forgetPasswordDto);
    }
    //修改密码
    @PostMapping("/updatePassword")
    @Operation(summary = "修改密码",description = "修改密码接口，手机号，旧密码，新密码")
    public SaResult updatePassword(@RequestBody @Validated UpdatePasswordDTO updatePasswordDto){
        return userService.updatePassword(updatePasswordDto);
    }
    //上传头像
    @PostMapping(value = "/uploadAvatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @Operation(summary = "上传头像",description = "上传头像")
    public SaResult uploadAvatar(@RequestParam("file")MultipartFile file){
        try {
            if(file == null || file.getSize() == 0){
                return SaResult.error("上传图片不能为空");
            }
            String fileName = file.getOriginalFilename();
            //String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1); // jpg
            String fileExt = FileNameUtil.extName(fileName); // jpg，不是.jpg
            Long fileSize = file.getSize();
            if(! IMAGE_TYPE.contains(fileExt)){
                return SaResult.error("上传图片格式错误，仅支持(.jpg,.jpeg,.png)格式");
            }
            if(fileSize > multipartConfigElement.getMaxFileSize()){
                return SaResult.error("上传图片大小不能超过10MB");
            }
            //原始文件名
            String originalFilename = file.getOriginalFilename();
            //截取原始文件名的后缀
            String extension=originalFilename.substring(originalFilename.lastIndexOf("."));
            //构造新文件名称
            String objectName= UUID.randomUUID().toString()+extension;
            //文件的请求路径
            String filePath=aliOssUtil.upload(file.getBytes(),objectName);
            //用mybtisplus将路径存入数据库
            User user = new User();
            user.setAvatar(filePath);
            QueryWrapper<User> wrapper = new QueryWrapper<User>()
                    .eq("id",StpUtil.getLoginId());
            userService.update(user,wrapper);

            return SaResult.ok(filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return SaResult.error("文件上传失败");
    }



}
